#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct person {
    char name[16];
    int  age;

    void (*set_age)(struct person *p, int age);
    int (*get_age)(struct person *p);

    void (*set_name)(struct person *p, const char *name);
    char *(*get_name)(struct person *p);

    struct person *(*clone)(struct person *p);

} person_t;

void set_age(struct person *p, int age) { p->age = age; }

int get_age(struct person *p) { return p->age; }

void set_name(struct person *p, const char *name) { strcpy(p->name, name); }

char *get_name(struct person *p) { return p->name; }

struct person *clone(struct person *p)
{
    struct person *new_obj = NULL;

    new_obj = (struct person *)malloc(sizeof(*new_obj));

    memset(new_obj, 0, sizeof(*new_obj));

    new_obj->age = p->age;
    strcpy(new_obj->name, p->name);
    new_obj->clone    = clone;
    new_obj->set_name = set_name;
    new_obj->set_age  = set_age;
    new_obj->get_name = get_name;
    new_obj->get_age  = get_age;

    return new_obj;
}

struct person *create_person(const char *name, int age)
{
    struct person *new_obj = NULL;

    new_obj = (struct person *)malloc(sizeof(*new_obj));

    memset(new_obj, 0, sizeof(*new_obj));

    new_obj->age = age;
    strcpy(new_obj->name, name);
    new_obj->clone    = clone;
    new_obj->set_name = set_name;
    new_obj->set_age  = set_age;
    new_obj->get_name = get_name;
    new_obj->get_age  = get_age;
    return new_obj;
}

struct person *destroy_person(struct person *p)
{
    if (p != NULL) {
        free(p);
    }
    return NULL;
}

int main()
{
    struct person *p    = NULL;
    struct person *c    = NULL;
    char *         name = "john";
    int            age  = 19;

    p = create_person(name, age);

    printf("person: %p &{\"name\":\"%s\", \"age\":%d}\n", p, p->name, p->age);

    c = p->clone(p);
    printf("person: %p &{\"name\":\"%s\", \"age\":%d}\n", c, c->name, c->age);

    p = destroy_person(p);
    c = destroy_person(c);

    return 0;
}
